using System;
using System.IO;
using System.Threading;

public static class Program {
   public static void Main() {
      //ReadMultipleFiles(@"C:\Boot.ini", @"c:\Point.cs");
      // Open the file indicating asynchronous I/O
      FileStream fs = new FileStream(@"C:\Boot.ini", FileMode.Open, 
         FileAccess.Read, FileShare.Read, 1024, 
         FileOptions.Asynchronous);

      Byte[] data = new Byte[100];

      // Initiate an asynchronous read operation against the FileStream
      IAsyncResult ar = fs.BeginRead(data, 0, data.Length, null, null);

      // Executing some other code here would be useful...

      // Suspend this thread until the asynchronous 
      // operation completes and get the result
      Int32 bytesRead = fs.EndRead(ar);

      // No other operations to do, close the file
      fs.Close();

      // Now, it is OK to access the byte array and show the result.
      Console.WriteLine("Number of bytes read={0}", bytesRead);
      Console.WriteLine(BitConverter.ToString(data, 0, bytesRead));
   }

   private static void ReadMultipleFiles(params String[] pathnames) {
      AsyncStreamRead[] asrs = new AsyncStreamRead[pathnames.Length];

      for (Int32 n = 0; n < pathnames.Length; n++) {
         // Open the file indicating asynchronous I/O
         Stream stream = new FileStream(pathnames[n], FileMode.Open,
            FileAccess.Read, FileShare.Read, 1024,
            FileOptions.Asynchronous);

         // Initiate an asynchronous read operation against the Stream
         asrs[n] = new AsyncStreamRead(stream, 100);
      }

      // All streams have been opened and all read requests have been 
      // queued; they are all executing concurrently!

      // Now, let's get and display the results
      for (Int32 n = 0; n < asrs.Length; n++) {
         Byte[] bytesRead = asrs[n].EndRead();

         // Now, it is OK to access the byte array and show the result.
         Console.WriteLine("Number of bytes read={0}", bytesRead.Length);
         Console.WriteLine(BitConverter.ToString(bytesRead));
      }
   }

   private sealed class AsyncStreamRead {
      private Stream       m_stream;
      private IAsyncResult m_ar;
      private Byte[]       m_data;

      public AsyncStreamRead(Stream stream, Int32 numBytes) {
         m_stream = stream;
         m_data = new Byte[numBytes];

         // Initiate an asynchronous read operation against the Stream
         m_ar = stream.BeginRead(m_data, 0, numBytes, null, null);
      }

      public Byte[] EndRead() {
         // Suspend this thread until the asynchronous 
         // operation completes and get the result
         Int32 numBytesRead = m_stream.EndRead(m_ar);

         // No other operations to do, close the stream
         m_stream.Close();

         // Resize the array to save space
         Array.Resize(ref m_data, numBytesRead);

         // Return the bytes
         return m_data;
      }
   }
}
